package com.qudian.pay.redis;

import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.google.common.primitives.Primitives;
import com.qudian.pay.core.utils.JdkSerializer;
import com.qudian.pay.redis.exception.RedisException;
import com.qudian.pay.redis.support.ICache;
import redis.clients.jedis.ShardedJedis;

/**
 * @Description: redis key/value 操作管理器
 * @ClassName: RedisKVManager
 * @author gaoxiang
 * @date 2016年11月21日 下午3:04:49
 */ 
@Component
public class RedisKVManager extends RedisManager implements ICache<String> {
	
	@Override
	public void set(String key, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.set((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public void set(String key, Object value, long timeout, TimeUnit unit) {
		if (StringUtils.isBlank(key))
			return;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.setex((key == null ? null : key.getBytes(charset)), (int) unit.toSeconds(timeout),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Boolean setNx(String key, Object value) {
		if (StringUtils.isBlank(key))
			return false;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.setnx((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value)) > 0;
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public <T> T get(Object key, Class<T> classOfT) {
		if (null == key)
			return null;
		ShardedJedis jedis = this.getReadPool().getResource();
		try {
			byte[] bytes = jedis.get((key == null ? null : ((String) key).getBytes(charset)));
			if (null == bytes)
				return null;
			return Primitives.wrap(classOfT).cast(JdkSerializer.deSerialize(bytes));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public <T> T getAndSet(String key, Object value, Class<T> classOfT) {
		if (StringUtils.isBlank(key) || null == value)
			return null;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return Primitives.wrap(classOfT).cast(JdkSerializer.deSerialize(jedis.getSet((key.getBytes(charset)), JdkSerializer.serialize(value))));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Integer append(String key, String value) {
		if (StringUtils.isBlank(key))
			return null;
		ShardedJedis jedis = this.getReadPool().getResource();
		try {
			Long val = jedis.append(key, value);
			if (null == val) {
				return null;
			}
			return val.intValue();
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public String get(String key, long start, long end) {
		if (StringUtils.isBlank(key))
			return null;
		ShardedJedis jedis = this.getReadPool().getResource();
		try {
			return jedis.getrange(key, start, end);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public void set(String key, Object value, long offset) {
		if (StringUtils.isBlank(key))
			return;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.setrange((key == null ? null : key.getBytes(charset)), offset,
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public void expire(String lockKey, int i) {
		if (StringUtils.isBlank(lockKey))
			return;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.expire(lockKey == null ? null : lockKey.getBytes(charset), i);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
}
